package com.zycfc.zsf.boot.job.common;

import org.springframework.util.*;
import com.google.common.collect.*;
import java.util.*;
import org.apache.ibatis.session.*;
import com.zycfc.zsf.boot.core.common.*;
import com.google.common.base.*;
import com.zycfc.zsf.boot.util.json.*;
import java.sql.*;
import org.slf4j.*;
import java.util.concurrent.*;

public class ShardStorage
{
    private static final Logger log;
    private static final String SET_QUERY_SQL = "/*proxy*/ show status";
    private static Map<String, List<Integer>> partitions;
    private static Map<String, Map<Integer, Map<String, List<Integer>>>> jobPartitions;
    
    private ShardStorage() {
    }
    
    public static Map<String, List<Integer>> getPartition() {
        return ShardStorage.partitions;
    }
    
    public static void setPartitions(final Map<String, List<Integer>> partitions) {
        ShardStorage.partitions = partitions;
    }
    
    public static Map<String, Map<Integer, Map<String, List<Integer>>>> getJobPartitions() {
        return ShardStorage.jobPartitions;
    }
    
    public static Map<String, List<Integer>> getPartition(final String jobName, final Integer shardingItem, final int shardingTotalCount) {
        if (!CollectionUtils.isEmpty((Map)ShardStorage.partitions) && !ShardStorage.jobPartitions.containsKey(jobName)) {
            synchronized (ShardStorage.class) {
                if (!CollectionUtils.isEmpty((Map)ShardStorage.partitions) && !ShardStorage.jobPartitions.containsKey(jobName)) {
                    try {
                        initJobPartitions(jobName, shardingTotalCount);
                    }
                    catch (Exception e) {
                        ShardStorage.log.error(e.getMessage(), (Throwable)e);
                    }
                }
            }
        }
        return CollectionUtils.isEmpty((Map)ShardStorage.jobPartitions.get(jobName)) ? Collections.EMPTY_MAP : ((Map<String, List<Integer>>)ShardStorage.jobPartitions.get(jobName).get(shardingItem));
    }
    
    private static void initJobPartitions(final String jobName, final int shardingTotalCount) throws Exception {
        final int setsNum = ShardStorage.partitions.keySet().size();
        final List<Integer> partitionsList = getDbPartitionsList();
        Collections.sort(partitionsList);
        if (shardingTotalCount < setsNum || shardingTotalCount > partitionsList.size()) {
            throw new IllegalArgumentException(String.format("zsfJob: @ZsfJob\u5206\u7247\u6570\u91cf\u914d\u7f6e\u9519\u8bef, \u4e0d\u80fd\u5c11\u4e8e\u6570\u636e\u5e93set\u6570\u91cf\u4e14\u4e0d\u8d85\u8fc7\u6570\u636e\u5e93\u5206\u7247\u603b\u6570\u91cf, jobName is [%s], shardingTotalCount is [%s]", jobName, shardingTotalCount));
        }
        if (partitionsList.size() % shardingTotalCount > 0) {
            throw new IllegalArgumentException(String.format("zsfJob: @ZsfJob\u5206\u7247\u6570\u91cf\u914d\u7f6e\u9519\u8bef, \u5206\u7247\u6570\u91cf\u914d\u7f6e\u9519\u8bef\uff0c\u5fc5\u987b\u662f2\u7684\u5e42\u6b21\u65b9, jobName is [%s], shardingTotalCount is [%s]", jobName, shardingTotalCount));
        }
        final int itemCountPerSharding = partitionsList.size() / shardingTotalCount;
        int count = 0;
        final Map<Integer, Map<String, List<Integer>>> shardItemMap = new LinkedHashMap<Integer, Map<String, List<Integer>>>();
        for (int i = 0; i < shardingTotalCount; ++i) {
            final Map<String, List<Integer>> dbShardMap = new LinkedHashMap<String, List<Integer>>();
            final List<Integer> dbShardingItems = new ArrayList<Integer>(itemCountPerSharding);
            String setName = "";
            for (int j = count * itemCountPerSharding; j < (count + 1) * itemCountPerSharding; ++j) {
                dbShardingItems.add(j);
                if (StringUtils.isEmpty((Object)setName)) {
                    setName = getSetName(j);
                    if (StringUtils.isEmpty((Object)setName)) {
                        throw new IllegalArgumentException(String.format("zsfJob: \u5206\u7247\u903b\u8f91\u5f02\u5e38\uff0c1\u4e2a\u4efb\u52a1\u5206\u7247\u4e0d\u80fd\u6267\u884c2\u4e2a\u5206\u533aset\u7684\u6570\u636e, jobName is [%s], shardingTotalCount is [%s]", jobName, shardingTotalCount));
                    }
                }
                else if (!setName.equals(getSetName(j))) {
                    throw new IllegalArgumentException(String.format("zsfJob: \u5206\u7247\u903b\u8f91\u5f02\u5e38\uff0c1\u4e2a\u4efb\u52a1\u5206\u7247\u4e0d\u80fd\u6267\u884c2\u4e2a\u5206\u533aset\u7684\u6570\u636e, jobName is [%s], shardingTotalCount is [%s]", jobName, shardingTotalCount));
                }
            }
            dbShardMap.put(setName, dbShardingItems);
            shardItemMap.put(i, dbShardMap);
            ++count;
        }
        ShardStorage.jobPartitions.put(jobName, shardItemMap);
    }
    
    private static String getSetName(final int j) {
        for (final String setName : ShardStorage.partitions.keySet()) {
            final List<Integer> partitionsList = ShardStorage.partitions.get(setName);
            if (partitionsList.contains(j)) {
                return setName;
            }
        }
        return null;
    }
    
    private static List<Integer> getDbPartitionsList() {
        final List<Integer> partitionsList = (List<Integer>)Lists.newArrayList();
        for (final List<Integer> list : ShardStorage.partitions.values()) {
            partitionsList.addAll(list);
        }
        return partitionsList;
    }
    
    public static Map<String, List<Integer>> queryPartitions() {
        final Map<String, List<Integer>> latestPartitions = new LinkedHashMap<String, List<Integer>>(8, 1.0f);
        try (final Connection connection = ((SqlSessionFactory)SpringContextHelper.getBean((Class)SqlSessionFactory.class)).openSession().getConnection();
             final Statement statement = connection.createStatement();
             final ResultSet resultSet = statement.executeQuery("/*proxy*/ show status")) {
            final Map<String, String> map = new LinkedHashMap<String, String>(32, 1.0f);
            while (resultSet.next()) {
                final String statusName = resultSet.getString("status_name");
                final String value = resultSet.getString("value");
                if (!StringUtils.isEmpty((Object)statusName)) {
                    map.put(statusName, value);
                }
            }
            if (!CollectionUtils.isEmpty((Map)map)) {
                final List<String> setKeys = (List<String>)Splitter.on(',').omitEmptyStrings().trimResults().splitToList((CharSequence)map.get("set"));
                ShardStorage.log.debug("zsfJob: query db set is [{}] !", (Object)JsonUtils.objectToJson((Object)setKeys));
                for (final String setKey : setKeys) {
                    final String hashRange = map.get(setKey + ":hash_range");
                    final List<String> ranges = (List<String>)Splitter.on("---").omitEmptyStrings().trimResults().splitToList((CharSequence)hashRange);
                    final int start = Integer.parseInt(ranges.get(0));
                    final int end = Integer.parseInt(ranges.get(1));
                    final List<Integer> partitionsList = (List<Integer>)Lists.newArrayList();
                    for (int i = start; i <= end; ++i) {
                        partitionsList.add(i);
                    }
                    latestPartitions.put(setKey, partitionsList);
                }
                ShardStorage.log.debug("zsfJob: query db partitions is [{}] !", (Object)JsonUtils.objectToJson((Object)latestPartitions));
            }
        }
        catch (Exception e) {
            ShardStorage.log.debug("zsfJob: can not query db partitions info, msg info is [{}]", (Object)e.getMessage(), (Object)e);
        }
        return latestPartitions;
    }
    
    static {
        log = LoggerFactory.getLogger((Class)ShardStorage.class);
        ShardStorage.partitions = new LinkedHashMap<String, List<Integer>>(8, 1.0f);
        ShardStorage.jobPartitions = new ConcurrentHashMap<String, Map<Integer, Map<String, List<Integer>>>>(8, 1.0f);
    }
}
